//
//  JCObjectFilter.m
//  JCSDK
//
//  Created by master on 16/3/22.
//  Copyright © 2016年 AdMaster. All rights reserved.
//

#import "JCObjectFilter.h"

@implementation JCObjectFilter


- (NSArray *)apply:(NSArray *)views {
    NSMutableArray *result = [NSMutableArray array];
    Class class = NSClassFromString(_name);
    //if class 非空 或_name 为通配符
    if(class || [_name isEqualToString:@"*"]) {
        for (NSObject *view  in views) {
            // get view 所有的subview | viewcontroller 所有childviewcontroller(if class_type = UIViewController) + presentedVC的view(if class_type = view) |  UITable 所有的cell 根据y坐标 排序
            NSArray *children = [self getChildrenOfObject:view ofType:class];
            if(_index && [_index unsignedIntegerValue] < [children count]) {
                if([view isKindOfClass:[UIView class]]) {
                    children = @[children[[_index unsignedIntegerValue]]];
                } else {
                    children = @[];
                }
            }
            [result addObjectsFromArray:children];
        }
    }
    
    if(!self.nameOnly) {
        if(self.unique && [result count] != 1) {
            return @[];
        }
        if(self.predicate) {
            return [result filteredArrayUsingPredicate:self.predicate];
        }
    }
    return [result copy];
}
- (NSArray *)applyReverse:(NSArray *)views {
    NSMutableArray *result = [NSMutableArray array];
    for (NSObject *view in views) {
        if ([self appliesTo:view]) {
            [result addObjectsFromArray:[self getParentsOfObject:view]];
        }
    }
    return [result copy];

}


/**
 *  合法性校验
 *
 *  @param view target
 *
 *  @return 是否合法
 */
- (BOOL)appliesTo:(NSObject *)view {
    
    
//    NSLog(@"\n匹配信息view%@",view);
//    NSLog(@"index : %d",self.index);
//    NSLog(@"是否通配符: %d",[self.name isEqualToString:@"*"]);
//    NSLog(@"类名结果: %d",[view isKindOfClass:NSClassFromString(self.name)]);
//    NSLog(@"正则结果: %d",self.nameOnly || (!self.predicate || [_predicate evaluateWithObject:view]));
//    NSLog(@"index 结果: %d",(!self.index || [self isView:view siblingNumber:[_index integerValue]])); // 在index位置 为该view
//    NSLog(@"unique 结果: %d",(!(self.unique) || [self isView:view oneOfNSiblings:1])); //父view 上唯一一个
    NSLog(@"%@",(([self.name isEqualToString:@"*"] || [view isKindOfClass:NSClassFromString(self.name)])
                 && (self.nameOnly || (
                                       (!self.predicate || [_predicate evaluateWithObject:view])
                                       && (!self.index || [self isView:view siblingNumber:[_index integerValue]])
                                       && (!(self.unique) || [self isView:view oneOfNSiblings:1])))
                 ) ? @"通过" : @"refuse");

    return (([self.name isEqualToString:@"*"] || [view isKindOfClass:NSClassFromString(self.name)])
            && (self.nameOnly || (
                                  (!self.predicate || [_predicate evaluateWithObject:view])
                                  && (!self.index || [self isView:view siblingNumber:[_index integerValue]])
                                  && (!(self.unique) || [self isView:view oneOfNSiblings:1])))
            );

}

/**
 *  返回所有的filter 是否校验通过 ,all pass return yes ,otherwise no
 *
 *  @param views view
 *
 *  @return 是否合法
 */
- (BOOL)appliesToAny:(NSArray *)views {
    for (NSObject *view in views) {
        if ([self appliesTo:view]) {
            return YES;
        }
    }
    return NO;
}

/**
 *  匹配view在父view中的index
 *
 *  @param view
 *  @param number index
 *
 *  @return
 */
- (BOOL)isView:(NSObject *)view siblingNumber:(NSInteger)number
{
    return [self isView:view siblingNumber:number of:-1];
}

/**
 *  匹配view的父view的subviews.cout
 *
 *  @param view
 *  @param number cout
 *
 *  @return
 */
- (BOOL)isView:(NSObject *)view oneOfNSiblings:(NSInteger)number
{
    return [self isView:view siblingNumber:-1 of:number];
}

/**
 *  判断view 在父view中的条件是否match  规则: index < 0 则匹配父view的subviews.count  numSiblings< 0 则匹配view 在父view的index
 *
 *  @param view
 *  @param index       view 在父view的index
 *  @param numSiblings view的subviews.count
 *
 *  @return 
 */
- (BOOL)isView:(NSObject *)view siblingNumber:(NSInteger)index of:(NSInteger)numSiblings
{
    NSArray *parents = [self getParentsOfObject:view];
    for (NSObject *parent in parents) {
        if ([parent isKindOfClass:[UIView class]]) {
            NSArray *siblings = [self getChildrenOfObject:parent ofType:NSClassFromString(_name)];
            if ((index < 0 || ((NSUInteger)index < [siblings count] && siblings[(NSUInteger)index] == view))
                && (numSiblings < 0 || [siblings count] == (NSUInteger)numSiblings)) {
                return YES;
            }
        }
    }
    return NO;
}


/**
 *  get view 获取superview nextResponder,UIViewController 获取parentViewController  rootVC 添加UIWindow
 *
 *  @param obj obj
 *
 *  @return
 */
- (NSArray *)getParentsOfObject:(NSObject *)obj
{
    NSMutableArray *result = [NSMutableArray array];
    if ([obj isKindOfClass:[UIView class]]) {
        if ([(UIView *)obj superview]) {
            [result addObject:[(UIView *)obj superview]];
        }
        // For UIView, nextResponder should be its controller or its superview.
        if ([(UIView *)obj nextResponder] && [(UIView *)obj nextResponder] != [(UIView *)obj superview]) {
            [result addObject:[(UIView *)obj nextResponder]];
        }
    } else if ([obj isKindOfClass:[UIViewController class]]) {
        if ([(UIViewController *)obj parentViewController]) {
            [result addObject:[(UIViewController *)obj parentViewController]];
        }
        if ([(UIViewController *)obj presentingViewController]) {
            [result addObject:[(UIViewController *)obj presentingViewController]];
        }
        if ([UIApplication sharedApplication].keyWindow.rootViewController == obj) {
            //TODO is there a better way to get the actual window that has this VC
            [result addObject:[UIApplication sharedApplication].keyWindow];
        }
    }
    return [result copy];
}

/**
 *  get view 所有的subview | viewcontroller 所有childviewcontroller(if class_type = UIViewController) + presentedVC的view(if class_type = view) |  UITable 所有的cell 根据y坐标 排序
 *
 *  @param obj   obj
 *  @param class class filter
 *
 *  @return
 */
- (NSArray *)getChildrenOfObject:(NSObject *)obj ofType:(Class)class
{
    NSMutableArray *children = [NSMutableArray array];
    // A UIWindow is also a UIView, so we could in theory follow the subviews chain from UIWindow, but
    // for now we only follow rootViewController from UIView.
    if ([obj isKindOfClass:[UIWindow class]] && [((UIWindow *)obj).rootViewController isKindOfClass:class]) {
        [children addObject:((UIWindow *)obj).rootViewController];
    } else if ([obj isKindOfClass:[UIView class]]) {
        // NB. For UIViews, only add subviews, nothing else.
        // The ordering of this result is critical to being able to
        // apply the index filter.
        for (NSObject *child in [(UIView *)obj subviews]) {
            if (!class || [child isKindOfClass:class]) {
                [children addObject:child];
            }
        }
    } else if ([obj isKindOfClass:[UIViewController class]]) {
        UIViewController *viewController = (UIViewController *)obj;
        for (NSObject *child in [viewController childViewControllers]) {
            if (!class || [child isKindOfClass:class]) {
                [children addObject:child];
            }
        }
        if (viewController.presentedViewController && (!class || [viewController.presentedViewController isKindOfClass:class])) {
            [children addObject:viewController.presentedViewController];
        }
        if (!class || (viewController.isViewLoaded && [viewController.view isKindOfClass:class])) {
            [children addObject:viewController.view];
        }
    }
    NSArray *result;
    // Reorder the cells in a table view so that they are arranged by y position
    if ([class isSubclassOfClass:[UITableViewCell class]]) {
        result = [children sortedArrayUsingComparator:^NSComparisonResult(UIView *obj1, UIView *obj2) {
            if (obj2.frame.origin.y > obj1.frame.origin.y) {
                return NSOrderedAscending;
            } else if (obj2.frame.origin.y < obj1.frame.origin.y) {
                return NSOrderedDescending;
            }
            return NSOrderedSame;
        }];
    } else {
        result = [children copy];
    }
    return result;
}
@end
